#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<vorbis/codec.h>
#include<vorbis/vorbisfile.h>
#include<fcntl.h>
#include<ao/ao.h>
#include<errno.h>

int ogg_play(int default_driver,FILE *oggbitstream)
{
	char pcmout[4096];
	

	/*initialize*/
	ao_sample_format format;
	format.bits=16;
//	format.channels=2;
//	format.rate=44100;
	format.byte_format=AO_FMT_LITTLE;
	/*open driver*/
	ao_device *device;
/*
	if(device==NULL){
		printf("error open device.\n");
		if(errno==AO_ENODRIVER){
			fprintf(stderr,"AO_ENODRIVER \n");
		}else if(errno==AO_ENOTLIVE){
			fprintf(stderr,"AO_ENOTLIVE \n");
		}else if(errno==AO_EBADOPTION){
			fprintf(stderr,"AO_EBADOPTION\n");
		}else if(errno==AO_EOPENDEVICE){
			fprintf(stderr,"AO_EOPENDEVICE\n");
		} else {
			fprintf(stderr,"AO_EFAIL \n");
		}
		return 1;
	}
*/
	/*play vorbis file*/

	OggVorbis_File vf;
	int eof=0;
	int current_section;

	if (ov_open(oggbitstream,&vf,NULL,0)<0){
		fprintf(stderr, "unknown format\n");
		return 2;
	}

	{
		char **ptr=ov_comment(&vf,-1)->user_comments;
		vorbis_info *vi=ov_info(&vf,-1);
		while(*ptr){
			printf("%s\n",*ptr);
			++ptr;
		}

		printf("\nBitstream is %d channel, %ldHz\n",vi->channels,vi->rate);
		format.channels=vi->channels;
		format.rate=vi->rate;
		device=ao_open_live(default_driver,&format,NULL/*no option*/);
	if(device==NULL){
		printf("error open device.\n");
		if(errno==AO_ENODRIVER){
			fprintf(stderr,"AO_ENODRIVER \n");
		}else if(errno==AO_ENOTLIVE){
			fprintf(stderr,"AO_ENOTLIVE \n");
		}else if(errno==AO_EBADOPTION){
			fprintf(stderr,"AO_EBADOPTION\n");
		}else if(errno==AO_EOPENDEVICE){
			fprintf(stderr,"AO_EOPENDEVICE\n");
		} else {
			fprintf(stderr,"AO_EFAIL \n");
		}
		return 1;
	}

		printf("\nDecoded length: %ld samples\n",(long)ov_pcm_total(&vf,-1));
		printf("Encoded by: %s\n\n",ov_comment(&vf,-1)->vendor);
	}

	while(!eof){
		long ret=ov_read(&vf,pcmout,sizeof(pcmout),0,2,1,&current_section);
		if (ret == 0) {
			/* EOF */
			eof=1;
		} else if (ret < 0) {
			/* error in the stream.  Not a problem, just reporting it in
			 *  case we (the app) cares.  In this case, we don't. */
		} else {
			/* we don't bother dealing with sample rate changes, etc, but
			 * you'll have to*/
			if(ao_play(device, pcmout, ret)==0){
				fprintf(stderr,"ao_play error \n");
			}
		}
	}

	/*close and shutdown*/

	if (ao_close(device)!=1){
		fprintf(stderr, "ao_close error \n");
	}
	return 0;

}
